﻿using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Silver3D.Math;

namespace Silver3D.Tests.Math
{
    /// <summary>
    /// Summary description for Vec2
    /// </summary>
    [TestClass]
    public class Vec2Tests
    {
        public Vec2Tests()
        {
            //
            // TODO: Add constructor logic here
            //
        }

        private TestContext testContextInstance;

        /// <summary>
        ///Gets or sets the test context which provides
        ///information about and functionality for the current test run.
        ///</summary>
        public TestContext TestContext
        {
            get
            {
                return testContextInstance;
            }
            set
            {
                testContextInstance = value;
            }
        }

        #region Additional test attributes
        //
        // You can use the following additional attributes as you write your tests:
        //
        // Use ClassInitialize to run code before running the first test in the class
        // [ClassInitialize()]
        // public static void MyClassInitialize(TestContext testContext) { }
        //
        // Use ClassCleanup to run code after all tests in a class have run
        // [ClassCleanup()]
        // public static void MyClassCleanup() { }
        //
        // Use TestInitialize to run code before running each test 
        // [TestInitialize()]
        // public void MyTestInitialize() { }
        //
        // Use TestCleanup to run code after each test has run
        // [TestCleanup()]
        // public void MyTestCleanup() { }
        //
        #endregion


        [TestMethod]
        public void Vec2_Static()
        {
            Assert.AreEqual(0.0, Vec2.Zero.X);
            Assert.AreEqual(0.0, Vec2.Zero.Y);
        }

        [TestMethod]
        public void Vec2_Constructor()
        {
            Vec2 w = new Vec2();
            Vec2 v = new Vec2(w);
            Assert.AreEqual(0.0, v.X);
            Assert.AreEqual(0.0, v.Y);

            v = new Vec2(1.0, 2.0);
            Assert.AreEqual(1.0, v.X);
            Assert.AreEqual(2.0, v.Y);

            v = new Vec2(new Vec3(1.0, 2.0, 3.0));
            Assert.AreEqual(1.0, v.X);
            Assert.AreEqual(2.0, v.Y);

            v = new Vec2(new Vec4(1.0, 2.0, 3.0, 4.0));
            Assert.AreEqual(1.0, v.X);
            Assert.AreEqual(2.0, v.Y);
        }

        [TestMethod]
        public void Vec2_Length()
        {
            Vec2 v = new Vec2(2.0, 0.0);
            Assert.AreEqual(4.0, v.LengthSquared);
            Assert.AreEqual(2.0, v.Length);
        }

        [TestMethod]
        public void Vec2_Indexer()
        {
            Vec2 v = new Vec2(1.0, 2.0);
            Assert.AreEqual(1.0, v[0]);
            Assert.AreEqual(2.0, v[1]);
        }

        [TestMethod]
        [ExpectedException(typeof(ArgumentOutOfRangeException))]
        public void Vec2_IndexerRange()
        {
            Vec2 v = new Vec2();
            double z = v[2];
        }

        [TestMethod]
        public void Vec2_Math()
        {
            Vec2 v = new Vec2(1.0, 2.0);
            v = -v;
            Assert.AreEqual(-1.0, v.X);
            Assert.AreEqual(-2.0, v.Y);

            v += 2.0;
            Assert.AreEqual(1.0, v.X);
            Assert.AreEqual(0.0, v.Y);

            v += new Vec2(1.0, 2.0);
            Assert.AreEqual(2.0, v.X);
            Assert.AreEqual(2.0, v.Y);

            v -= 2.0;
            Assert.AreEqual(0.0, v.X);
            Assert.AreEqual(0.0, v.Y);

            v -= new Vec2(1.0, 2.0);
            Assert.AreEqual(-1.0, v.X);
            Assert.AreEqual(-2.0, v.Y);

            v *= -1.0;
            Assert.AreEqual(1.0, v.X);
            Assert.AreEqual(2.0, v.Y);

            v *= new Vec2(2.0, 1.0);
            Assert.AreEqual(2.0, v.X);
            Assert.AreEqual(2.0, v.Y);

            v /= 2.0;
            Assert.AreEqual(1.0, v.X);
            Assert.AreEqual(1.0, v.Y);

            v /= new Vec2(-1.0, -1.0);
            Assert.AreEqual(-1.0, v.X);
            Assert.AreEqual(-1.0, v.Y);

            Assert.AreEqual(2.0, v.Dot(new Vec2(-1.0, -1.0)));

            v = new Vec2(1.0, 0.0);
            v = v.Unit;
            Assert.AreEqual(1.0, v.X);
            Assert.AreEqual(0.0, v.Y);
        }

        [TestMethod]
        public void Vec2_Chaining()
        {
            Vec2 v = new Vec2(2.0) * 2.0 / 2.0;
            Assert.AreEqual(2.0, v.X);
            Assert.AreEqual(2.0, v.Y);
        }

        [TestMethod]
        public void Vec2_Equals()
        {
            Vec2 a = new Vec2(1.0, 2.0);
            Vec2 b = new Vec2(1.0, 2.0);
            Vec2 c = new Vec2(1.0, 0.0);

            Assert.IsTrue(a == b);
            Assert.IsFalse(a != b);
            Assert.IsTrue(a <= b);
            Assert.IsTrue(a >= b);
            Assert.IsTrue(a > c);
            Assert.IsTrue(c < a);
        }
    }
}
